package com.myweb.dao.common;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.myweb.common.ResponseList;

/**
 * 
 * @TODO  基础数据库访问实现类
 * @author roye
 * @date Apr 17, 2013 11:44:40 AM
 * @version V1.0
 */
@SuppressWarnings("unchecked")
@Repository
public class CBaseDaoImpl<T extends Serializable, PK extends Serializable>
		extends HibernateDaoSupport implements IBaseDao<T, PK> {
	
	private static final Log log = LogFactory.getLog(CBaseDaoImpl.class);

	@Resource(name="sessionFactory")
	public void setSessionFactory_(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}
	
	// 实体类类型(由构造方法自动赋值)
	private Class<T> entityClass;

	// 构造方法，根据实例类自动获取实体类类型
	@SuppressWarnings("unchecked")
	public CBaseDaoImpl() {
		this.entityClass = null;
		Class c = getClass();
		Type t = c.getGenericSuperclass();
		if (t instanceof ParameterizedType) {
			Type[] p = ((ParameterizedType) t).getActualTypeArguments();
			this.entityClass = (Class<T>) p[0];
		}
	}
	
	/**
	 * 
	 * @todo  将查询的list封装到responseList对象中
	 * @author roye
	 * @date Apr 19, 2013 3:24:09 PM
	 * @param   
	 * @return ResponseList<E>   
	 * @throws
	 */
	protected <E> ResponseList<E> buildResponseList(List<E> paramList)
	  {
	    ResponseList localResponseList = new ResponseList(paramList.size());
	    localResponseList.addAll(paramList);
	    paramList = null;
	    return localResponseList;
	 }
	
	/**
	 * 
	 * @todo  按条件查询对象集合分页
	 * @author roye
	 * @date Apr 17, 2013 5:08:30 PM
	 * @param   
	 * @return T  
	 * @throws
	 */
	public ResponseList<T> getResponseList(StringBuffer sql,int startRow,int endRow){
		ResponseList<T> list = null;
		try {
			SQLQuery query = this.getSession().createSQLQuery(sql.toString());
			//对原生sql 查询使用ResultTransformer。这会返回不受Hibernate管理的实体
			query.setResultTransformer(Transformers.aliasToBean(entityClass));
			query.setFirstResult(startRow);
			query.setMaxResults(endRow);
			list = this.buildResponseList(query.list());
		} catch (RuntimeException e) {
			log.error("按条件查询对象集合分页 " + entityClass + " failed", e);
			throw e;
		} finally{
			this.getSession().close();
		}
		return list;
	}
	
	/**
	 * 
	 * @todo  按条件查询对象集合
	 * @author roye
	 * @date Apr 17, 2013 5:08:30 PM
	 * @param   
	 * @return T  
	 * @throws
	 */
	public List<T> getObjectListByCondition(StringBuffer sql){
		List<T> list = null;
		try {
			SQLQuery query = this.getSession().createSQLQuery(sql.toString()).addEntity(entityClass);
			list = query.list();
		} catch (RuntimeException e) {
			log.error("getObjectByCondition " + entityClass + " failed", e);
			throw e;
		} finally{
			this.getSession().close();
		}
		return list;
	}
	
	
	
	/**
	 * 
	 * @todo 按条件查询对象
	 * @author roye
	 * @date Apr 17, 2013 5:24:41 PM
	 * @param   
	 * @return T   
	 * @throws
	 */
	public T getObjectByCondition(StringBuffer sql){
		Query query = this.getSession().createSQLQuery(sql.toString()).addEntity(entityClass);
		return (T)query.uniqueResult();
	}
	
	/**
	 * 
	 * @todo  查询count
	 * @author roye
	 * @date Apr 17, 2013 5:25:29 PM
	 * @param   
	 * @return int 总数  
	 * @throws
	 */
	public int getCount(StringBuffer sql) {
		int count = 0;
		try {
			SQLQuery query = this.getSession().createSQLQuery(sql.toString());
			count = (Integer) query.uniqueResult();
		} catch (RuntimeException e) {
			log.error("getCount " + entityClass + " failed", e);
			throw e;
		} finally {
			this.getSession().close();
		}
		return count;
	}

	/**
	 * 
	 * @todo 通用修改方法
	 * @author roye
	 * @date Apr 19, 2013 3:52:59 PM
	 * @param   sql 
	 * @return boolean   
	 * @throws
	 */
	public boolean updateStatus(StringBuffer sql){
		try
        {
            int result = getSession().createSQLQuery(sql.toString())
                    .executeUpdate();
            if (result > 0)
            {
                return true;
            }
        } catch (Exception e)
        {
            return false;
        } finally {
			this.getSession().close();
		}
        return true;
        
	}
	

	// -------------------- 基本检索、增加、修改、删除操作 --------------------

	// 根据主键获取实体。如果没有相应的实体，返回 null。
	public T get(PK id) {
		log.debug("getting " + entityClass + " instance with id: " + id);
		try {
			return (T) getHibernateTemplate().get(entityClass, id);
		} catch (RuntimeException e) {
			log.error("get " + entityClass + " failed", e);
			throw e;
		}

	}

	// 根据主键获取实体。如果没有相应的实体，抛出异常。
	public T load(PK id) {
		log.debug("loading " + entityClass + " instance with id: " + id);
		try {
			return (T) getHibernateTemplate().load(entityClass, id);
		} catch (RuntimeException e) {
			log.error("loading " + entityClass + " failed", e);
			throw e;
		}
	}


	// 更新实体
	public void update(T entity) {
		log.debug("update " + entityClass + " instance ");
		try {
			getHibernateTemplate().update(entity);
		} catch (RuntimeException e) {
			log.error("update " + entityClass + " instance failed", e);
			throw e;
		}

	}

	// 存储实体到数据库
	public void save(T entity) {
		log.debug("save " + entityClass + " instance ");
		try {
			getHibernateTemplate().save(entity);
		} catch (RuntimeException e) {
			log.error("save " + entityClass + " instance failed", e);
			throw e;
		}
	}

	// 增加或更新实体
	public void saveOrUpdate(T entity) {
		log.debug("saveOrUpdate " + entityClass + " instance ");
		try {
			getHibernateTemplate().saveOrUpdate(entity);
		} catch (RuntimeException e) {
			log.error("saveOrUpdate " + entityClass + " instance failed", e);
			throw e;
		}
	}


	// 删除指定的实体
	public void delete(T entity) {
		log.debug("delete " + entityClass + " instance ");
		try {
			getHibernateTemplate().delete(entity);
		} catch (RuntimeException e) {
			log.error("delete " + entityClass + " instance failed", e);
			throw e;
		}
	}

	// 根据主键删除指定实体
	public void deleteByKey(PK id) {
		log.debug("deleteByKey " + entityClass + " instance ");
		try {
			this.delete(this.load(id));
		} catch (RuntimeException e) {
			log.error("deleteByKey " + entityClass + " instance failed", e);
			throw e;
		}
	}


	// -------------------- HSQL ----------------------------------------------

	// 使用HSQL语句直接增加、更新、删除实体
	public int bulkUpdate(String queryString) {
		log.debug("bulkUpdate " + entityClass + " sql: " + queryString);
		try {
			return getHibernateTemplate().bulkUpdate(queryString);
		} catch (RuntimeException e) {
			log.error("bulkUpdate " + entityClass + " instance failed sql: "
					+ queryString, e);
			throw e;
		}

	}

	// 使用带参数的HSQL语句增加、更新、删除实体
	public int bulkUpdate(String queryString, Object[] values) {
		log.debug("bulkUpdate " + entityClass + " sql: " + queryString);
		try {
			return getHibernateTemplate().bulkUpdate(queryString, values);
		} catch (RuntimeException e) {
			log.error("bulkUpdate " + entityClass + " instance failed sql: "
					+ queryString, e);
			throw e;
		}
	}

	// 使用HSQL语句检索数据
	public List find(String queryString) {
		log.debug("find " + entityClass + " sql: " + queryString);
		try {
			return getHibernateTemplate().find(queryString);
		} catch (RuntimeException e) {
			log.error("find " + entityClass + " instance failed sql: "
					+ queryString, e);
			throw e;
		}
	}

	// 使用带参数的HSQL语句检索数据
	public List find(String queryString, Object[] values) {
		log.debug("find " + entityClass + " sql: " + queryString);
		try {
			return getHibernateTemplate().find(queryString, values);
		} catch (RuntimeException e) {
			log.error("find " + entityClass + " instance failed sql: "
					+ queryString, e);
			throw e;
		}

	}

	// 使用带命名的参数的HSQL语句检索数据
	public List findByNamedParam(String queryString, String[] paramNames,
			Object[] values) {
		return getHibernateTemplate().findByNamedParam(queryString, paramNames,
				values);
	}

	// 使用命名的HSQL语句检索数据
	public List findByNamedQuery(String queryName) {
		return getHibernateTemplate().findByNamedQuery(queryName);
	}

	// 使用带参数的命名HSQL语句检索数据
	public List findByNamedQuery(String queryName, Object[] values) {
		return getHibernateTemplate().findByNamedQuery(queryName, values);
	}

	// 使用带命名参数的命名HSQL语句检索数据
	public List findByNamedQueryAndNamedParam(String queryName,
			String[] paramNames, Object[] values) {
		return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName,
				paramNames, values);
	}

	// 强制立即更新缓冲数据到数据库（否则仅在事务提交时才更新）
	public void flush() {
		getHibernateTemplate().flush();
	}
}
